#pragma once

#include <iostream>
#include <windows.h>

#include "image.h"
#include "ref.h"

/** 
 * \ingroup ti6
 *
 * \brief
 * DIB stands for Device Independent Bitmap, which is a Windows term for
 * bitmap images with an accompanying format description. This format
 * contains information such as the bit depth (colors), size and resolution.
 * DIB is the only class in the application which can handle formats with
 * a bit depth other than 24 (full color). The convertTo() method is
 * called to convert loaded images to full color (this will also be done
 * for thumbnail images).
 *
 * Copyright (c) Academie voor ICT en Media 2007 - 2008
 */
class DIB
{
public:
	typedef Ref<BITMAPINFO> Format;

	/**
	 \brief
	 Default constructor. This creates an empty instance, which means it
	 does not contain any image.
	 */
	DIB();

	/**
	 \brief
	 Copy constructor. Creates a deep copy of the given DIB.
	 
	 \param DIB& The instance to copy.
	 */
	DIB( const DIB& );

	/**
	 \brief
	 Destructor. This will invalidate the pointer returned by data().
	 */
	~DIB();

	/**
	 \brief
	 Copy the specified DIB to this instance. This will invalidate the
	 previous contents of this instance.
	 
	 \param DIB& The DIB to copy.
	 \return This instance.
	 */
	DIB& operator =( const DIB& );

	/**
	 \brief
	 Get an image description for a part of the DIB. When no rectangle
	 is given, an image description of the whole DIB is returned.

	 \param *rect The part of the DIB, for which the image description
	   should be created.
	 \return An Image instance which points to data within this DIB.
	   This instance described the part specified by rect, and can be
	   used to manipulate the image.
	 */
	Image getImage( RECT *rect = NULL );

	/**
	 \brief
	 Read a bitmap file from a stream. This function supports Windows
	 bitmap images of all sizes and formats.
	 
	 \param &strm An input stream, which starts at the beginning of
	   a bitmap (BMP) file.
	 \return If the bitmap is successfully loaded, true is returned.
	   False is returned otherwise.
	 */
	bool readBitmap( std::istream &strm );

	/**
	 \brief
	 Write a bitmap to a stream.
	 
	 \param &strm An output stream.
	 \return If the bitmap is successfully saved, true is returned.
	   False is returned otherwise.
	 */
	bool saveBitmap( std::ostream &strm );

	/**
	 \brief
	 Create a bitmap. The format must have been specified previously,
	 which can be done using setFormat().
	 
	 \return If the bitmap is successfully saved, true is returned.
	   False is returned otherwise.
	 */
	bool create();

	/**
	 \brief
	 Set the data and for this DIB. This function will not do any
	 conversion or validation.
	 
	 \param *data The raw bitmap data (excluding header).
	 \param dataSize The size of the bitmap, in bytes.
	 */
	void setData( unsigned char *data, unsigned int dataSize );

	/**
	 \brief
	 Get the raw bitmap data for this DIB.
	 
	 \return A pointer to the bitmap data. Do not delete this value.
	 */
	unsigned char* data();

	/**
	 \brief
	 Get the size of the raw data, in bytes.
	 
	 \return The bitmap size.
	 */
	unsigned int dataSize() const;

	/**
	 \brief
	 Set the format for this DIB. This function will not do any
	 conversion or validation.
	 
	 \param format The bitmap format.
	 */
	void setFormat( Format format );

	/**
	 \brief
	 Get the bitmap format for this DIB. This structure is a Windows specific
	 bitmap description, which contains information like the size, bit depth and
	 resolution.
	 
	 \return The bitmap format.
	 */
	Format format();

	/**
	 \brief
	 Get the width and height of the bitmap, in pixels.
	 
	 \return A SIZE struct which contains the size of the bitmap.
	 */
	SIZE size() const;

	/**
	 \brief
	 Get the bit depth of the bitmap.
	 
	 \return The bit depth of the bitmap.
	 */
	WORD bitCount() const;

	/**
	 \brief
	 Request whether this bitmap is stored bottom up. That is, the row
	 stored first is at the very bottom of the image.
	 
	 \return If the bitmap is bottom up, true is returned. If false
	   is returned, the bitmap is top down.
	 */
	bool bottomUp() const;

	/**
	 \brief
	 Request whether this bitmap is stored top down. That is, the row
	 stored first is at the very top of the image.
	 
	 \return If the bitmap is top down, true is returned. If false
	   is returned, the bitmap is top down.
	 */
	bool topDown() const;

	/**
	 \brief
	 Copy the image to another DIB instance, while converting the
	 format of the image.
	 
	 \param &dib An output parameter containing the new image, in the
	   specified format.
	 \param format The format for the new image (dib).
	 \return If the image is successfully copied and converted, true
	   is returned. False is returned in case of an error.
	 */
	bool convertTo( DIB &dib, Format format ) const;
private:
	/**
	 \brief
	 Get the size of a bitmap, given a header structure. This does not
	 always have to be a BITMAPINFOHEADER. The exact header version
	 depends on the biSize member. The header types supported are
	 BITMAPINFOHEADER, BITMAPV4HEADER, BITMAPV5HEADER and
	 BITMAPCOREHEADER.
	 
	 \param BITMAPINFOHEADER* A pointer to the header, may not be NULL.
	 \return A SIZE struct which contains the size of the bitmap.
	 */
	static SIZE size( const BITMAPINFOHEADER* );

	/**
	 Raw bitmap data.
	 */
	unsigned char *_data;

	/**
	 Size of the raw data buffer, in bytes.
	 */
	unsigned int _dataSize;

	/**
	 The image format. This describes various information about the bitmap,
	 like the size, bit depth and resolution.
	 */
	Format _format;
};
